package com.blog.boot.shiro;

import com.blog.boot.api.entity.UserEntity;
import com.blog.boot.api.system.Permission;
import com.blog.boot.api.system.Role;
import com.blog.boot.api.system.service.SystemService;
import com.blog.boot.api.system.service.UserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.List;
import java.util.Set;

public class ShiroRealm extends AuthorizingRealm {

    @Autowired
    UserService userService;
    @Autowired
    SystemService systemService;
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        UserEntity user =(UserEntity) principals.getPrimaryPrincipal();
        //得到用户角色
        Role roleByRoleid = systemService.getRoleByRoleid(user.getRole());

        authorizationInfo.addRole(roleByRoleid.getRoleValue());//添加用户角色 这里角色只有一种
        Set<Integer> permissions = roleByRoleid.getPermissions();
        //根据用户权限id查权限
        List<Permission> perMissionByPerM = systemService.getPerMissionByPerM(permissions);
        perMissionByPerM.stream().forEach(e->
                authorizationInfo.addStringPermission(e.getPermissionValue())
        );
        return authorizationInfo;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        Subject subject = SecurityUtils.getSubject();
        Session session = subject.getSession();
        //获取用户的输入的账号
        String username = (String) token.getPrincipal();
        //这里需注意。看别人的教程有人是这样写的String password = (String) token.getCredentials();
        //项目运行的时候报错，发现密码不正确。后来进源码查看发现将密码注入后。Shiro会进行转义将字符串转换成字符数组。
        //源码：this(username, password != null ? password.toCharArray() : null, false, null);
        //不晓得是否是因为版本的原因，建议使用的时候下载源码进行查看
        UserEntity user = userService.findUserByUserName(username);
        //通过username从数据库中查找 User对象，如果找到，没找到.
        /*SysUser user = userService.selectByAccount(username);*/
        if(null == user){
            throw new UnknownAccountException();
        }else {
            if("1".equals(user.getStart())){
                throw new LockedAccountException();
            }else if ("2".equals(user.getStart())){
                throw new DisabledAccountException();
            }else{
                SimpleAuthenticationInfo simpleAuthenticationInfo = null;
                try {
                    simpleAuthenticationInfo = new SimpleAuthenticationInfo(user, user.getPassword(), getName());
                } catch (Exception e) {
                    e.printStackTrace();
                }
                session.setAttribute("user",user);
                return simpleAuthenticationInfo;
            }
        }
    }
}
